package com.zhaodui.fxy;

import com.alibaba.fastjson.JSONObject;
import jodd.http.HttpRequest;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;

import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.util.StreamUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RequestUtil {

    /**
     * 请求 get 数据
     * @param httpUrl
     * @param paramsMap
     * @return
     */
    public static String getData(String httpUrl,Map<String,String> paramsMap){

        return postData(httpUrl,paramsMap,null,"GET");
    }

    public static InputStream getInputStream(String httpUrl, Map<String,String> paramsMap,String contentType,String method){

        return getInputStream(httpUrl,paramsMap,contentType,method,null);
    }

    /**
     * 获取数据流
     * @param httpUrl
     * @param paramsMap
     * @param contentType
     * @param method
     * @return
     */
    public static InputStream getInputStream(String httpUrl, Map<String,String> paramsMap,String contentType,String method,File file){
        try {
            URL url = new URL(httpUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            if (method == null || "".equals(contentType)){
                conn.setRequestMethod("POST");
            }else{
                conn.setRequestMethod(method);
            }


            if (contentType == null || "".equals(contentType)){
                contentType = "application/x-www-form-urlencoded";
            }
            /**
             * conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
             **/
            //conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Content-Type", contentType);

            conn.setConnectTimeout(10 * 1000);
            conn.setReadTimeout(10 * 1000);
            conn.setDoOutput(true);
            // 返回参数
            OutputStream out = conn.getOutputStream();
            StringBuffer paramsSb = new StringBuffer();
            String paramsStr = "";
            if (paramsMap != null && paramsMap.size() > 0){
                if ("application/json".equals(contentType)) {
                    JSONObject json = (JSONObject) JSONObject.toJSON(paramsMap);
                    paramsStr = json.toJSONString();
                } else {
                    for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
                        paramsSb.append(entry.getKey() + "=" + entry.getValue().toString());
                        paramsSb.append("&");
                    }
                    paramsStr = paramsSb.toString().substring(0, paramsSb.toString().length() - 1);
                }
            }
            System.out.println("请求参数:"+paramsStr);
            out.write(paramsStr.getBytes());

            out.flush();
            int responseCode = conn.getResponseCode();
            InputStream in;
            if (responseCode == 200) {
                in = conn.getInputStream();
            } else {
                in = conn.getErrorStream();
            }

            return in;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * post 数据
     * @param httpUrl
     * @param paramsMap
     * @param contentType
     * @return
     */
    public static String postData(String httpUrl, Map<String,String> paramsMap,String contentType,String method){

        try {
            InputStream in = getInputStream(httpUrl,paramsMap,contentType,method);
            String responseStr = StreamUtils.copyToString(in, Charset.forName(fxjConstant.utf8));
            return responseStr;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 下载数据
     * @param httpUrl
     * @param paramsMap
     * @param contentType
     * @param method
     * @param filePath
     */
    public static String downloadData(String httpUrl, Map<String,String> paramsMap,String contentType,String method,String filePath){
        return downloadData(httpUrl,paramsMap,contentType,method,new File(filePath));
    }
    /**
     * get 请求下载
     * @param url
     * @param params
     * @param outFilePath
     * @return
     */
    public static String downloadFileByGet(String url, Map<String, Object> params, String outFilePath) {

        return downloadFile(url, params, "GET", null, outFilePath);
    }
    /**
     * 下载文件
     *
     * @param url
     * @param params
     * @param method
     * @param contentType
     * @param outFilePath
     * @return
     */
    public static String downloadFile(String url, Map<String, Object> params, String method, String contentType, String outFilePath) {
        HttpRequest httpRequest = null;
        if (method == null) {
            method = "POST";
        }
        method = method.toUpperCase();
        if ("GET".equals(method)) {
            httpRequest = HttpRequest.get(url);
        } else {
            httpRequest = HttpRequest.post(url);
        }
        if (params == null) {
            params = new HashMap<>();
        }

        if (StringUtil.isEmpty(contentType)) {
            contentType = "application/x-www-form-urlencoded";
        }

        httpRequest.contentType(contentType);

        jodd.http.HttpResponse httpResponse = httpRequest.form(params).send();
        byte[] bytes = httpResponse.bodyBytes();

        try {
            FileUtils.writeByteArrayToFile(new File(outFilePath), bytes);
            return "success";
        } catch (IOException e) {
         }
        return "fail";
    }
    /**
     * 下载数据
     * @param httpUrl
     * @param paramsMap
     * @param contentType
     * @param method
     * @param file
     */
    public static String downloadData(String httpUrl, Map<String,String> paramsMap,String contentType,String method,File file){
        try {
            InputStream in = getInputStream(httpUrl,paramsMap,contentType,method);
            OutputStream outputStream = new FileOutputStream(file);

            if (in == null || outputStream == null){
                return "fail";
            }

            StreamUtils.copy(in,outputStream);
            return "success";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "fail";
    }

    public static String downloadFormData(String httpUrl, Map<String,String> paramsMap,File file){

        return downloadData(httpUrl,paramsMap,"application/x-www-form-urlencoded","POST",file);
    }

    public static String downloadJsonData(String httpUrl, Map<String,String> paramsMap,File file){
        return downloadData(httpUrl,paramsMap,"application/json","POST",file);
    }

    /**
     * post content-type为application/x-www-form-urlencoded 表单 数据
     * @param httpUrl
     * @param paramsMap
     * @return
     */
    public static String postFormData(String httpUrl, Map<String,String> paramsMap){
        return postData(httpUrl,paramsMap,"application/x-www-form-urlencoded","POST");
    }

    /**
     * post content-type为application/json json 数据
     * @param httpUrl
     * @param paramsMap
     * @return
     */
    public static String postJsonData(String httpUrl, Map<String,String> paramsMap){
        return postData(httpUrl,paramsMap,"application/json","POST");
    }

    /**
     * 获取项目根路径
     */
    public static String getProjectBasePath(HttpServletRequest req){
        return req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + req.getContextPath() + "/";
    }

    /**
     * 多文件上传
     * @param url
     * @param params 文本参数
     * @param fileParams 文件参数 暂支持 Map<String,File>,Map<String,List<File>> 类型的数据
     * @return
     */
    public static String postFileMultiPart(String url,Map<String,String> params,Map<String,Object> fileParams){
        CloseableHttpClient httpclient = HttpClients.createDefault();

        try {
            // 创建httpget.
            HttpPost httppost = new HttpPost(url);

            //setConnectTimeout：设置连接超时时间，单位毫秒。setConnectionRequestTimeout：设置从connect Manager获取Connection 超时时间，单位毫秒。这个属性是新加的属性，因为目前版本是可以共享连接池的。setSocketTimeout：请求获取数据的超时时间，单位毫秒。 如果访问一个接口，多少时间内无法返回数据，就直接放弃此次调用。
            RequestConfig defaultRequestConfig = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(5000).setSocketTimeout(15000).build();
            httppost.setConfig(defaultRequestConfig);

            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            //文本参数
            if (params != null){
                for(Map.Entry<String,String> param : params.entrySet()){
                    multipartEntityBuilder.addPart(param.getKey(), new StringBody(param.getValue(), Charset.forName("utf-8")));
                }
            }

            //文件参数
            if (fileParams != null){
                for(Map.Entry<String,Object> param : fileParams.entrySet()){
                    Object obj = param.getValue();
                    if (obj instanceof File){
                        multipartEntityBuilder.addPart(param.getKey(),new FileBody((File) obj));
                    }else if (obj instanceof List){
                        List<Object> files = (List) obj;
                        for (Object objFile:files){
                            if (objFile instanceof File){
                                multipartEntityBuilder.addPart(param.getKey(),new FileBody((File) objFile));
                            }else{
                                          throw new  BaseBusinessException("e1","文件参数:"+param.getKey()+"值List里元素不是File类型");
                             }
                        }
                    }else {
                        throw new  BaseBusinessException("e1", "文件参数:"+param.getKey()+"值的数据类型暂不支持");

                     }
                }
            }
            HttpEntity reqEntity = multipartEntityBuilder.build();
            httppost.setEntity(reqEntity);

            // 执行post请求.
            CloseableHttpResponse response = httpclient.execute(httppost);

            System.out.println("got response");

            try {
                // 获取响应实体
                HttpEntity entity = response.getEntity();
                System.out.println("--------------------------------------");
                // 打印响应状态
                System.out.println(response.getStatusLine());
                if (entity != null) {
                    String result = EntityUtils.toString(entity,Charset.forName("UTF-8"));
                    System.out.println("返回结果:" + result);
                    return result;
                }
                System.out.println("------------------------------------");
            } finally {
                response.close();

            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static void main(String[] args) throws Exception {
        String httpUrl = "http://localhost:8080/enotary-signature/opensignapi/sign/file/uploadFile.json";
        Map<String,String> parmas = new HashMap<>();
        parmas.put("userId","中地");
        parmas.put("appId","fdsafds");
        File file1 = new File("E:\\logo.png");
        File file2 = new File("E:\\logo1.png");

        List<File> files = new ArrayList<>();
        files.add(file1);
        files.add(file2);
        Map<String,Object> fileParams = new HashMap<>();
        fileParams.put("files",files);
        fileParams.put("file",file2);


        String result = postFileMultiPart(httpUrl,parmas,fileParams);
        System.out.println(result);
    }
}
